package com.bicntech.common.utils.file;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.text.CharSequenceUtil;
import com.bicntech.common.exception.ServiceException;
import com.bicntech.common.utils.JSON;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.sl.extractor.SlideShowExtractor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.IIOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Iterator;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class FileUtils {
    /**
     * 下载文件名重新编码
     *
     * @param response      响应对象
     * @param realFileName  真实文件名
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName){
        String percentEncodedFileName =percentEncode(realFileName);

        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);

        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
    }

    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static  String percentEncode(String s) {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8);
        // \\+ -> \+,\+ -> +; %20 -> 空格
        return encode.replaceAll("\\+","%20");
    }


    /**
     * 将MultipartFile转为File
     *
     * @param mulFile
     * @return
     */
    public static File multipartFileToFile(MultipartFile mulFile) throws IOException {
        InputStream ins = mulFile.getInputStream();
        String fileName = mulFile.getOriginalFilename();
        String prefix = getFileNameNoEx(fileName) + UUID.fastUUID();
        String suffix = "." + getExtensionName(fileName);
        File toFile = File.createTempFile(prefix, suffix);
        OutputStream os = new FileOutputStream(toFile);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
        return toFile;
    }


    public static String getExtensionName(String filename){
        if ((filename != null) && (filename.length() > 0)) {
           int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }

    /**
     * 获取不带扩展名的文件名
     */
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }
    /**
     * 效验文件开内容是否为空
     * pdf、xls、xlsx、doc、docx、ppt
     *
     * @param file      文件
     * @param condition 文件类型
     * @return true  为空   false  不为空
     */
    public static Boolean isEmpty(MultipartFile file, String condition) throws IOException {
        if (file == null) return Boolean.FALSE;

        if ("xls".equals(condition) || "xlsx".equals(condition)) {
            //判断为excel
            if (!isSheetNotEmpty(file)) {
                return true;
            }
        } else {
            //判断为word
            if (file.isEmpty()) {
                return true;
            }
        }
        return false;
    }



    public static Boolean isEmptyNoThrow(MultipartFile file, String condition) {
        try {
            return FileUtils.isEmpty(file, condition);
        } catch (IOException e) {
            log.warn("file check empty error ", e);
            return Boolean.FALSE;
        }
    }

    /**
     * 判断excel 内容是否为空
     *
     * @param file 文件
     * @return true  不为空
     */
    public static boolean isSheetNotEmpty(MultipartFile file) {
        try {
            //判断什么类型文件
            Workbook workbook = null;
            try {
                workbook = new HSSFWorkbook(file.getInputStream());
            } catch (OfficeXmlFileException e) {
                workbook = new XSSFWorkbook(file.getInputStream());
            }
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                Iterator<Row> iterator = workbook.getSheetAt(i).rowIterator();
                while (iterator.hasNext()) {
                    Row row = iterator.next();
                    Iterator<Cell> cells = row.cellIterator();
                    while (cells.hasNext()) {
                        Cell cell = cells.next();
                        if (!cell.getStringCellValue().isEmpty()) {
                            return true;
                        }
                    }
                }
            }
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            log.info("excel次效验异常: IOException={}", JSON.toJSONString(e));
            throw new ServiceException("系统异常" + e);
        }
    }

    /**
     * 判断pdf内容是否为空
     *
     * @param data 文件数据
     * @return true 不为空   false 为空
     */
    public static boolean is_pdf(byte[] data) {
        if (data != null && data.length > 4 && data[0] == 37 && data[1] == 80 && data[2] == 68 && data[3] == 70 && data[4] == 45) {
            if (data[5] == 49 && data[6] == 46 && data[7] == 51 && data[data.length - 7] == 37 && data[data.length - 6] == 37 && data[data.length - 5] == 69 && data[data.length - 4] == 79 && data[data.length - 3] == 70 && data[data.length - 2] == 32 && data[data.length - 1] == 10) {
                return true;
            } else {
                return data[5] == 49 && data[6] == 46 && data[7] == 52 && data[data.length - 6] == 37 && data[data.length - 5] == 37 && data[data.length - 4] == 69 && data[data.length - 3] == 79 && data[data.length - 2] == 70 && data[data.length - 1] == 10;
            }
        } else {
            return false;
        }
    }


    /**
     * 判断ppt内容是否为空
     *
     * @param files 文件数据
     * @return true 不为空   false 为空
     */
    public static Boolean isPPTNotEmpty(MultipartFile files) {
        try {
            InputStream inputStream = new BufferedInputStream(files.getInputStream());
            SlideShowExtractor<?, ?> extractor = new SlideShowExtractor<>(new XMLSlideShow(inputStream));
            String cont = extractor.getText();
            if (CharSequenceUtil.isBlank(cont)) {
                return false;
            }
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new ServiceException("系统异常" + e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("系统异常" + e);
        }
    }

    /**
     * MultipartFile to File
     *
     * @param file 文件
     * @return File
     * @throws IOException
     */
    public File convert(MultipartFile file) throws IOException{
        File convFile = new File(file.getOriginalFilename());
        convFile.createNewFile();
        try (InputStream is = file.getInputStream()){
            Files.copy(is,convFile.toPath());
        }
        return convFile;
    }


}
